package com.qf.main.login.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.aliyun.sdk.service.dysmsapi20170525.AsyncClient;
import com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qf.common.base.ex.PhoneCodeException;
import com.qf.common.base.ex.ServiceException;
import com.qf.common.base.result.ResultStatus;
import com.qf.common.redis.dao.RedisDao;
import com.qf.common.sms.AliYunSmsConfigProperties;
import com.qf.main.login.common.vo.SysUserVo;
import com.qf.main.login.entity.SysUser;
import com.qf.main.login.mapper.SysUserMapper;
import com.qf.main.login.realm.UserToken;
import com.qf.main.login.service.SmsService;
import com.qf.main.login.service.SysUserService;
import com.qf.main.login.utils.CommonBeanutils;
import com.qf.main.login.utils.ShiroUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * @author chengqiang
 * @Create 2024-01-23-16:05
 * @Description:
 */
@Service
public class SmsServiceImpl implements SmsService {

    @Resource
    private RedisDao redisDao;
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private AsyncClient asyncClient;
    @Resource
    AliYunSmsConfigProperties properties;
    @Resource
    private ObjectMapper objectMapper;
    @Resource
    private SysUserService sysUserService;

    /**
     * 发送验证码
     * <p>
     * 1. 生成验证吗
     * 2.  保存到redis中
     *
     * @param phone
     * @return
     */
    @Override
    public String sendSms(String phone) {
        //生成存储路径
        String key = String.format("%s%s",REDIS_SMS_CODE_KEY_PREFIX,phone);
        try {
            if (!redisDao.hasKey(key)) {
                // 生成验证码
                String code = RandomUtil.randomNumbers(4);

                Map<String, String> templateParam = new HashMap<>();
                // 在redis存入一个map
                templateParam.put(SMS_CODE_TEMPLATE_PARAM, code);
                // 使用sms发送短信请求
                SendSmsRequest sendSmsRequest = SendSmsRequest.builder()
                        // sig名字
                        .signName(properties.getSignName())
                        // 模板代码
                        .templateCode(properties.getTemplateCode())
                        // 手机号码
                        .phoneNumbers(phone)
                        //
                        .templateParam(objectMapper.writeValueAsString(templateParam)).build();
                CompletableFuture<SendSmsResponse> completableFuture = asyncClient.sendSms(sendSmsRequest);
                SendSmsResponse sendSmsResponse = completableFuture.get();
                String responseCode = sendSmsResponse.getBody().getCode();
                code = ShiroUtils.encryption(code);
                // key键和code值和过期时间1分钟
                redisDao.setEx(key, code, Duration.ofMinutes(60));
                // templateParam.put(SMS_CODE_TEMPLATE_PARAM, ShiroUtils.encryption(code));
                if (!SMS_RESPONSE_RESULT_OK.equals(responseCode)) {
                    throw new ServiceException(ResultStatus.SMS_SEND_VERIFY_CODE_ERROR);
                }
            }
        } catch (Exception ex) {
            // ResultStatus.SYS_ERROR
            throw new ServiceException(ResultStatus.SYS_ERROR);
        }
        return "success";
    }
    @Override
    public  Integer registerValid(String phone,String code){
        System.out.println(phone+code);
        if(!ObjectUtils.isEmpty(sysUserMapper.selectUserByPhone(phone))){
            throw new ServiceException(ResultStatus.PHONE_DOES__EXIST);
        }
        String key = String.format("%s%s", SmsService.REDIS_SMS_CODE_KEY_PREFIX, phone);
        String redisCode = (String) redisDao.get(key);
        if(ShiroUtils.encryption(code).equals(redisCode)){
            return 0;
        }else {
            throw new PhoneCodeException(ResultStatus.SMS_VALID_CODE_ERROR);
        }
    }
    @Override
    public SysUserVo loginPhone(UserToken userToken) {
        Subject subject = SecurityUtils.getSubject();

        SysUser userInfo = sysUserService.getSysUserInfo(userToken.getUsername());
        if(ObjectUtils.isEmpty(userInfo)){
            throw new PhoneCodeException(ResultStatus.PHONE_DOES_NOT_EXIST);
        }
        if (userInfo.getDelStatus() != 0) {
            throw new PhoneCodeException(ResultStatus.BANNED_USER);
        }
        try {
            subject.login(userToken);

        }catch (IncorrectCredentialsException ice) {
            // 转化成自定义异常
            throw new PhoneCodeException(ResultStatus.SMS_SEND_VERIFY_CODE_ERROR);
        }  catch (AuthenticationException ae) {
            throw new PhoneCodeException(ResultStatus.SMS_SEND_VERIFY_CODE_ERROR);
        }
        SysUser principal = (SysUser) SecurityUtils.getSubject().getPrincipal();
        SysUserVo sysUserVo = CommonBeanutils.convertTo(principal, SysUserVo::new);
        sysUserVo.setToken(subject.getSession().getId().toString());
        return sysUserVo;

        // String key = String.format("%s%s", SmsService.REDIS_SMS_CODE_KEY_PREFIX, phone);
        // Object redisCode = redisDao.get(key);
        // if (ObjectUtils.isEmpty(redisCode)) {
        //     throw new ServiceException(ResultStatus.SMS_VERIFY_CODE_ERROR);
        // }
        // if (!code.equals(redisCode.toString())) {
        //     throw new ServiceException(ResultStatus.SMS_VERIFY_CODE_ERROR);
        // }
        // QueryWrapper<SysUser> qw = new QueryWrapper<>();
        // qw.lambda().eq(SysUser::getPhone, phone);
        // SysUser sysUser = sysUserMapper.selectOne(qw);
        // // SysUser user = (SysUser) SecurityUtils.getSubject().getPrincipal();
        // // return subject.getSession().getId().toString();
        // return "登录成功";


    }


}
